package ch.fusun.baron.core.datastructures;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * A map which maps in two directions (key->value and value->key
 * 
 * @param <T>
 *            The type of objects
 */
public class MirrorMap<T> {

	private final Map<T, T> keyMap = new HashMap<T, T>();
	private final Map<T, T> valueMap = new HashMap<T, T>();

	/**
	 * @param key
	 *            The key
	 * @return The value for the key
	 */
	public T get(T key) {
		T result = keyMap.get(key);
		if (result == null) {
			result = valueMap.get(key);
		}
		return result;
	}

	/**
	 * @param key
	 *            The key
	 * @param value
	 *            The value
	 */
	public void put(T key, T value) {
		keyMap.put(key, value);
		valueMap.put(value, key);
	}

	/**
	 * Clears the mappings
	 */
	public void clear() {
		keyMap.clear();
		valueMap.clear();
	}

	/**
	 * @return The set of all entries
	 */
	public Set<Pair<T>> entrySet() {
		Set<Pair<T>> result = new HashSet<Pair<T>>();
		for (Entry<T, T> entry : keyMap.entrySet()) {
			result.add(new Pair<T>(entry.getKey(), entry.getValue()));
		}
		return result;
	}

	/**
	 * @param entry
	 *            The entry to add
	 */
	public void put(Pair<T> entry) {
		keyMap.put(entry.getKey(), entry.getValue());
		valueMap.put(entry.getValue(), entry.getKey());
	}

	/**
	 * @return The key set
	 */
	public Collection<T> keySet() {
		return keyMap.keySet();
	}

	/**
	 * @param o
	 *            The object to remove
	 */
	public void remove(T o) {
		keyMap.remove(o);
		valueMap.remove(o);
	}

}
